package com.eling.elcms.travel.service.impl;

import com.eling.elcms.core.AppContext;
import com.eling.elcms.core.event.IEventListener;
import com.eling.elcms.core.exception.AppException;
import com.eling.elcms.core.exception.BusinessException;
import com.eling.elcms.core.model.BaseModel;
import com.eling.elcms.core.model.ModelUtils;
import com.eling.elcms.core.service.IGenericModelService;
import com.eling.elcms.core.service.ServiceLocator;
import com.eling.elcms.core.util.PropertyUtils;
import com.eling.elcms.privilege.service.impl.UserAfterSealUnSealEvent;
import com.eling.elcms.system.model.CommonUser;
import com.eling.elcms.travel.model.*;
import com.eling.elcms.travel.model.ApprovalDefine.Status;
import com.eling.elcms.travel.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ApproalServiceImpl implements IApprovalService {
	@Autowired
	private IGenericModelService genericModelService;
	@Autowired
	private IApprovalDefineService approvalDefineService;
	@Autowired
	private IApprovalInstanceService approvalInstanceService;
	@Autowired
	private IApprovalProcessService approvalProcessService;
	@Autowired 
	ITravelContractRefundManager travelContractRefundM;
	@Override
	public <T extends BaseModel> T commit(String businesstype, T model) {
		// 校验是否存在改审批流程,该审批流程是否启用
		ApprovalDefine app = new ApprovalDefine();
		app.setServiceType(businesstype);
		List<ApprovalDefine> adlist = approvalDefineService.query(app);
		if (adlist.isEmpty()) {
			throw new BusinessException("没有对应审批流程设置!");
		}
		app = adlist.get(0);
	
		if (app.getStatus() != Status.Setting) {
			throw new BusinessException(app.getDescription()+"审批流程没有启用!");
		}
		if (app.getApprovalDefineItems().isEmpty()) {
			throw new BusinessException("该审批流程没有设置明细流程!");
		}
		//把之前的产生的不通过的通知失效
		ICallbackService callbackService = ServiceLocator.getService(app.getServiceImpl());
		// 生成业务实例 ，和所有对应审批过程
		ApprovalInstance approvalInstance = new ApprovalInstance();
		approvalInstance.setApprovalDefine(app);
		approvalInstance.setCreateTime(new Date());
		approvalInstance.setModelId(ModelUtils.getId(model));
		approvalInstance.setPosition(0);
		approvalInstance.setFlowStatus(FlowStatus.Initial);
		approvalInstance = approvalInstanceService.save(approvalInstance);
		List<ApprovalProcess> apList = new ArrayList<ApprovalProcess>();
		for (ApprovalDefineItem approvalDefineItem : app.getApprovalDefineItems()) {
			ApprovalProcess approvalProcess = new ApprovalProcess();
			approvalProcess.setApprovalInstance(approvalInstance);
			approvalProcess.setSequenceNumber(approvalDefineItem.getSequenceNumber());

			if (approvalDefineItem.getSequenceNumber() == 0) {
				approvalProcess.setCommitTime(new Date());
				approvalProcess.setCreator((CommonUser) AppContext.curUser());
				approvalProcess.setChecker((CommonUser) AppContext.curUser());
				approvalProcess.setStatus(ApprovalProcess.Status.Commit);
				apList.add(approvalProcess);
			} else {
				approvalProcess.setStatus(ApprovalProcess.Status.Initial);
				 ApprovalRuleRegister arr  = approvalDefineItem.getApprovalRuleRegister();
				 IApprovalRule approvalRule = ServiceLocator.getService(arr.getRuleClass());
				 approvalProcess.setChecker((CommonUser) approvalRule.getApproval(approvalDefineItem.getArrKeyValue(), model));
				 apList.add(approvalProcess);
			}
		}
		apList = approvalProcessService.save(apList);
		callbackService.setFlowStatus(model, FlowStatus.Approvaling);
		return model;
	}
	/**
	 * 校验
	 * @param approvalProcess
	 * @param aplist
	 */
	private void verification(ApprovalProcess approvalProcess,
			List<ApprovalProcess> aplist) {
		// 当前用户是否有权限审核
		if (!approvalProcess.getChecker().getPkUser().equals(AppContext.curUser()
				.getPkUser()) ) {
			throw new BusinessException("对不起，您没有权限进行审批！");
		}
		// 判断是否越次审批
		boolean flag = false;
		for (ApprovalProcess tmp : aplist) {
			if (approvalProcess.getSequenceNumber() > tmp
					.getSequenceNumber()
					&& tmp.getStatus() == ApprovalProcess.Status.Initial) {
				flag = true;
				break;
			}

		}
		if (flag) {
			throw new BusinessException("对不起，您不能越次审批！");
		}
	}

	@Override
	public Map<String, Object> approval(ApprovalProcess approvalProcess) {
		approvalProcess.setCheckTime(new Date());
		BaseModel model = null;
		ICallbackService callbackService = ServiceLocator
				.getService(approvalProcess.getApprovalInstance().getApprovalDefine().getServiceImpl());
		Long modelId = approvalProcess.getApprovalInstance().getModelId();
		String modelClass = approvalProcess.getApprovalInstance()
				.getApprovalDefine().getModelClass();
		try {
			model = (BaseModel) genericModelService.getById(modelId,
					Class.forName(modelClass));
		} catch (Exception e) {
			throw  new AppException("类型错误");
		}
		ApprovalInstance approvalInstance = approvalProcess
				.getApprovalInstance();
		ApprovalProcess cond = new ApprovalProcess();
		cond.setApprovalInstance(approvalInstance);
		List<ApprovalProcess> aplist = approvalProcessService.query(cond);
		// 审批前的校验
		verification(approvalProcess, aplist);
		// 根据传入过程的状态（通过，不通过 ，代签 ），进行下一步操作
		if (approvalProcess.getStatus() == ApprovalProcess.Status.Agent) {
			agent(approvalProcess,model,callbackService);
			// 保存
			approvalProcess = approvalProcessService.save(approvalProcess);
		} else if(approvalProcess.getStatus() == ApprovalProcess.Status.Plus){
			plus(approvalProcess,model,callbackService);
		}else {
			// 保存
			approvalProcess = approvalProcessService.save(approvalProcess);
		}
//		actionManager.setFinishDateByFather(approvalProcess.getPkApprovalProcess(), "ApprovalProcess", TaskType.Approval);
		// 判断是否是该流程中的最后一个环节和是不通过，如果是要修改对应业务模型的状态
		aplist = approvalProcessService.query(cond);
		int now = approvalProcess.getSequenceNumber();
		int last = aplist.get(aplist.size() - 1)
				.getSequenceNumber();
		
		
		boolean lastPass= true;
		for (ApprovalProcess ap : aplist) {
			if(ap.getSequenceNumber()  == last 
					&&
				ap.getStatus() == ApprovalProcess.Status.Initial){
				lastPass = false;
			}
		}
		if (now == last
				|| approvalProcess.getStatus() == ApprovalProcess.Status.NotPass) {
			// 修改对应业务模型的状态
			if(lastPass 
					|| approvalProcess.getStatus() == ApprovalProcess.Status.NotPass){
				changeStatus(approvalProcess, aplist.get(0), model,aplist,callbackService,last);
			}
		} else {
			for (ApprovalProcess check : aplist) {
				if (check.getSequenceNumber().equals(approvalProcess
						.getSequenceNumber())) {
					if (check.getStatus() == ApprovalProcess.Status.Initial) {
					}
				}
			}
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("approval", approvalProcess);
		map.put("model", model);
		return map;
	}

	private  void changeStatus(ApprovalProcess approvalProcess,
			ApprovalProcess first, BaseModel model,List<ApprovalProcess> aplist,ICallbackService callbackService,Integer last) {
		ApprovalInstance instance =   approvalProcess.getApprovalInstance();
		
		if (approvalProcess.getStatus() == ApprovalProcess.Status.NotPass) {
			if(notPass(approvalProcess, aplist)){
				instance.setFlowStatus(FlowStatus.NotApproved);
				callbackService.setFlowStatus(model, FlowStatus.Initial);
				//删除其他的初始的处理过程
				for (ApprovalProcess removeap : aplist) {
					if(removeap.getStatus() == ApprovalProcess.Status.Initial){
						approvalProcessService.remove(removeap);
					}
				}
				approvalInstanceService.save(instance);
			}else if(!notPass(approvalProcess, aplist) &&approvalProcess.getSequenceNumber() == last && lastHasPass(aplist,last)){
				instance.setFlowStatus(FlowStatus.Approved);
				callbackService.setFlowStatus(model, FlowStatus.Approved);
				TravelContractRefund travelContractRefund = new TravelContractRefund();
				travelContractRefund.setTravelContract(((ReturnCredentials)model).getTravelContract());
				travelContractRefund.setStatus(TravelContractRefund.RefundStatus.NoRefund);
				travelContractRefund.setVersion(0);
				travelContractRefund.setRefundDate(new Date());
				travelContractRefundM.save(travelContractRefund);
			}
		} else  {
			instance.setFlowStatus(FlowStatus.Approved);
			callbackService.setFlowStatus(model, FlowStatus.Approved);
			approvalInstanceService.save(instance);
			TravelContractRefund travelContractRefund = new TravelContractRefund();
			travelContractRefund.setTravelContract(((ReturnCredentials)model).getTravelContract());
			travelContractRefund.setStatus(TravelContractRefund.RefundStatus.NoRefund);
			travelContractRefund.setVersion(0);
			travelContractRefund.setRefundDate(new Date());
			travelContractRefundM.save(travelContractRefund);
		}
	}

	private boolean lastHasPass(List<ApprovalProcess> aplist,Integer last) {
		for (ApprovalProcess approvalProcess : aplist) {
			if (approvalProcess.getSequenceNumber() == last) {
				if(approvalProcess.getStatus().equals(ApprovalProcess.Status.Pass)){
					return true;
				}
			}
		}
		return false;
	}
	private void  agent(ApprovalProcess approvalProcess,BaseModel model,ICallbackService callbackService) {
		// 在对应位置生成一个新的审核过程
		ApprovalProcess agent = new ApprovalProcess();
		agent.setApprovalInstance(approvalProcess.getApprovalInstance());
		agent.setSequenceNumber(approvalProcess.getSequenceNumber());
		agent.setChecker(approvalProcess.getAgentChecker());
		agent.setStatus(ApprovalProcess.Status.Initial);
		agent=approvalProcessService.save(agent);
	}
	
	private void  plus(ApprovalProcess approvalProcess,BaseModel model,ICallbackService callbackService) {
		approvalProcess.setStatus(ApprovalProcess.Status.Initial);
		approvalProcessService.save(approvalProcess);
		
		// 在对应位置生成一个新的审核过程
		ApprovalProcess plus = new ApprovalProcess();
		plus.setApprovalInstance(approvalProcess.getApprovalInstance());
		plus.setSequenceNumber(approvalProcess.getSequenceNumber());
		plus.setChecker(approvalProcess.getPlusChecker());
		plus.setStatus(ApprovalProcess.Status.Initial);
		plus.setNote("被"+approvalProcess.getChecker().getName()+"邀请加入审批");
		plus=approvalProcessService.save(plus);
	}

	private boolean notPass(ApprovalProcess approvalProcess,
			List<ApprovalProcess> aplist) {
		boolean change = false;
		boolean tmp  = true;
		int count = 0;
		for (ApprovalProcess ap : aplist) {
			if (ap.getSequenceNumber() == approvalProcess
					.getSequenceNumber()) {
				if(ap.getStatus() != ApprovalProcess.Status.NotPass){
					tmp = false;
				}
				
				count += count + 1;
			}
		}
		if (count == 1) {
			change = true;
		} 
		if(tmp){
			change = true;
		}
		return change;
	}

//	private void sendAction(String title, ApprovalProcess approvalProcess,boolean finalaction) {
//		Action action = new Action(title, TaskType.Approval, new Date(), null,
//				CreateType.Automatic, null);
//		action.setTargetType(TargetType.User);
//		action.setPkTarget(approvalProcess.getChecker().getPkUser());
//		
//		action.setPageLink(approvalProcess.getApprovalInstance()
//				.getApprovalDefine().getPageLink());
//		String params = "{" + "\"business\":\"approval\"," + "\"modelId\":\""
//				+ approvalProcess.getApprovalInstance().getModelId() + "\"}";
//		action.setPageParameter(params);
//		action.setPkFather(approvalProcess.getPkApprovalProcess());
//		action.setFatherType("ApprovalProcess");
//		if(finalaction){
//			action.setDeadline(
//					DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH), 3)
//					);
//		}else{
//			action.setDeadline(ElcmsDateUtils.MAX_DATE);	
//		}
//		actionManager.save(action);
//	}
//
//	@Override
//	public ApprovalProcess abandonApproval(ApprovalProcess approvalProcess,List<Long> nextApprovalprocesspk) {
//		approvalProcess=approvalProcessService.save(approvalProcess);
//		Action action = new Action();
//		action.setType(TaskType.Approval);
//		PropertyUtils.setProperty(action, "pkFatherIn", nextApprovalprocesspk);
//		List<Action> aclist =actionManager.query(action);
//		actionManager.remove(aclist);
//		return approvalProcess;
//	}

	@Override
	public BaseModel approvalTest(Long modelId, String modelClass) {
		ICallbackService callbackService = ServiceLocator
				.getService("com.eling.elcms.fp.service.impl.DefaultCallBackServiceImpl");
		BaseModel model;
		try {
			model = (BaseModel) genericModelService.getById(modelId,
					Class.forName(modelClass));
			callbackService.setFlowStatus(model, FlowStatus.Approved);
		} catch (ClassNotFoundException e) {
			throw new AppException("类型错误！");
		}
		return model;
	}
	@Service
	public static class UserSealEventListener  implements IEventListener<UserAfterSealUnSealEvent> {
	    @Autowired
		private IApprovalDefineItemService approvalDefineItemService;
	    @Autowired
		private IApprovalInstanceService approvalInstanceService;
	    
		@Override
		public void doEvent(UserAfterSealUnSealEvent event) {
			if(event.getUser().isSeal()){
				String definename = "";
				ApprovalDefineItem itemcond =  new ApprovalDefineItem();
				itemcond.setArrValue(event.getUser().getName());
				List<ApprovalDefineItem> itemlist = approvalDefineItemService.query(itemcond);
				if(itemlist.isEmpty()){
					return;
				}else{
					List<ApprovalDefine> definelist = new ArrayList<ApprovalDefine>();
					for (ApprovalDefineItem approvalDefineItem : itemlist) {
						definelist.add(approvalDefineItem.getApprovalDefine());
					}
					ApprovalInstance instancecond = new ApprovalInstance();
					PropertyUtils.setProperty(instancecond, "approvalDefineIn", definelist);
					List<ApprovalInstance> instancelist= approvalInstanceService.query(instancecond);
					if(instancelist.isEmpty()){
						return;
					}else{
						boolean flag = false;
						for (ApprovalInstance approvalInstance : instancelist) {
							if(approvalInstance.getFlowStatus() ==FlowStatus.Initial){
								flag = true;
								definename += approvalInstance.getApprovalDefine().getDescription()+",";
							}	
						}
						if(flag){
							throw new BusinessException("对不起，该会员有未完成的审批流程（"+definename.substring(0, definename.length()-1)+")");
						}
					}
				}
				
			}
			
		}
	}
	
	
	
}
